home *** CD-ROM | disk | FTP | other *** search
- ;==========================================================================;
- ; 8250 Services ;
- ; This code also used by the QUADRAM QUADPORT board and the ;
- ; 4 async port card without change. ;
- ; ;
- ; Copyright 1983 by William E. Westfield. All rights reserved. ;
- ; Copyright 1986, 1987, 1988, 1991 by H. Roy Engehausen. ;
- ; All rights reserved. ;
- ; ;
- ; This software may be freely distributed and used, but it may not ;
- ; under any circumstances be sold by anyone other than the author. ;
- ; It may be distributed by a commercial company as long as it is ;
- ; for no cost. ;
- ; ;
- ;==========================================================================;
-
- ;--------------------------------------------------------------------------;
- ; Branch to the proper service routine ;
- ; ;
- ; AH=0 INITIALIZE ;
- ; DX is the port number. (0 = COM1, 1 = COM2) ;
- ; AL is set according to the following table. ;
- ; ;
- ; High speed option is off ;
- ; MSB LSB ;
- ; 7 6 5 4 3 2 1 0 ;
- ; ----data-rate---- -Parity-- Stopbits --Word length-- ;
- ; ;
- ; 000 - 110 X0 - none 0 - 1 10 - 7 bits ;
- ; 001 - 150 01 - odd 1 - 2 11 - 8 bits ;
- ; 010 - 300 11 - even ;
- ; 011 - 600 ;
- ; 100 - 1200 ;
- ; 101 - 2400 ;
- ; 110 - 4800 ;
- ; 111 - 9600 ;
- ; ;
- ; High speed option is on ;
- ; 000 - 9600 X0 - none 0 - 1 10 - 7 bits ;
- ; 001 - 14400 01 - odd 1 - 2 11 - 8 bits ;
- ; 010 - 19200 11 - even ;
- ; 011 - 28800 ;
- ; 100 - 38400 ;
- ; 101 - 57600 ;
- ; 110 - 115200 ;
- ; 111 - 330400 ;
- ; ;
- ; Returns: ;
- ; AX = status according to function 3. ;
- ; DX = unchanged ;
- ; ;
- ; AH=1 SEND ;
- ; DX is the port number. (0 = COM1, 1 = COM2) ;
- ; AL is the character to be sent. ;
- ; Returns: ;
- ; AH = status according to function 3. ;
- ; AL = unchanged ;
- ; DX = unchanged ;
- ; ;
- ; AH=2 RECEIVE ;
- ; DX is the port number. (0 = COM1, 1 = COM2) ;
- ; ;
- ; Returns: ;
- ; AH = status according to function 3. ;
- ; AL = character read from buffer. ;
- ; DX = unchanged ;
- ; ;
- ; AH=3 STATUS ;
- ; DX is the port number. (0 = COM1, 1 = COM2) ;
- ; ;
- ; Returns: ;
- ; AH = Line Status Register ;
- ; AL = Modem Status Register ;
- ; DX = Unchanged ;
- ; ;
- ; If the extended 8250 functions are available, they are described later ;
- ;--------------------------------------------------------------------------;
-
- MOV BL,AH
- IF present_8250x
- CMP BL,12 ; Validate the function code
- ELSE
- CMP BL,3 ; Validate the function code
- ENDIF
- JA rsint_8250_exit ; Not a valid code
- SUB BH,BH ; Zero the high order byte
- SHL BL,1 ; * 2
- JMP rsint_8250_jmp[BX] ; Go to it
-
- rsint_8250_jmp LABEL WORD ;
- DW OFFSET rsint_8250_init ; 0 = Initialize
- DW OFFSET rsint_8250_send ; 1 = Send a character
- DW OFFSET rsint_8250_recv ; 2 = Receive character
- DW OFFSET rsint_8250_status ; 3 = Status
-
- IF present_8250x
-
- ; Extended function codes
-
- DW OFFSET rsint_8250_inquiry ; 4 = return footprint
- DW OFFSET rsint_8250_droprts ; 5 = signal NO RTS/DTR
- DW OFFSET rsint_8250_raiserts ; 6 = signal RTS/DTR
- DW OFFSET rsint_8250_sendbrk ; 7 = send break
- DW OFFSET rsint_8250_ndr ; 8 = non destructive read
- DW OFFSET rsint_8250_sopt ; 9 = set options
- DW OFFSET rsint_8250_buffw ; A = block write
- DW OFFSET rsint_8250_buffr ; B = block read
- DW OFFSET rsint_8250_ded ; C = DED mode send/receive
-
- ENDIF
-
- rsint_8250_exit:
- JMP rsint_exit ;
-
- ;==========================================================================;
- ; 8250 Bios constants ;
- ;==========================================================================;
-
- ;--------------------------------------------------------------------------;
- ; Divisors for the different data rates. The offset into the table ;
- ;is the one from the IBM BIOS initialization parameters ;
- ;--------------------------------------------------------------------------;
-
- divisor_8250 LABEL WORD ;
- DW 1047 ; 0 = 110
- DW 768 ; 1 = 150
- DW 384 ; 2 = 300
- DW 192 ; 3 = 600
- DW 96 ; 4 = 1200
- DW 48 ; 5 = 2400
- DW 24 ; 6 = 4800
- DW 12 ; 7 = 9600
-
- ; High speed options
- DW 12 ; 0 = 9600
- DW 9 ; 1 = 14400
- DW 6 ; 2 = 19200
- DW 4 ; 3 = 28800
- DW 3 ; 4 = 38400
- DW 2 ; 5 = 57600
- DW 1 ; 6 = 115200
- DW 0 ; 7 = 330400
-
- ;==========================================================================;
- ; Initialization routine ;
- ;==========================================================================;
-
- rsint_8250_init:
-
- ;--------------------------------------------------------------------------;
- ; Mark block as open ;
- ;--------------------------------------------------------------------------;
-
- OR flags[SI],flags_in_use ; This block is open!
-
- ;--------------------------------------------------------------------------;
- ; Set data rate ;
- ;--------------------------------------------------------------------------;
-
- MOV AH,AL ; Save the parms for later
-
- MOV BL,AH ; Look up the baud rate
- MOV CL,4 ; parameter
- ROL BL,CL ;
- AND BX,00001110B ;
- TEST options[SI],opt_high ; High speed option?
- JZ rsint_8250_init_nohs ; Nope
- ADD BX,00010000B ; Yep.. Offset
- rsint_8250_init_nohs: ;
- MOV BX,divisor_8250[BX] ;
-
- MOV CX,baseaddr[SI] ; Get base address for chip
- MOV DX,CX ; Address of LCR
- ADD DX,lcr_8250 ;
- MOV AL,lcr_8250_dlab ; Enable access to divisor
- OUT DX,AL ;
-
- MOV DX,CX ; Address of lower divisior half
- ADD DX,dll_8250 ;
- MOV AL,BL ; Put lower half
- OUT DX,AL ;
-
- MOV DX,CX ; Address of upper divisior half
- ADD DX,dlm_8250 ;
- MOV AL,BH ; Put upper half
- OUT DX,AL ;
-
- ;--------------------------------------------------------------------------;
- ; Set the data bits, stop bits, and parity ;
- ;--------------------------------------------------------------------------;
-
- MOV AL,AH ; Get parms back
- AND AL,00011111B ; Throw away baud rate leaving the rest
- MOV DX,CX ; Address of LCR
- ADD DX,lcr_8250 ;
- OUT DX,AL ; Output the parms
-
- ;--------------------------------------------------------------------------;
- ; Set interrupt enable register ;
- ;--------------------------------------------------------------------------;
-
- MOV AL,ier_8250_rda ; Enable data interrupt only
-
- TEST options[SI],opt_trbuf ; Transmit buffering turned on?
- JZ rsint_8250_initnotr ; No - Just want only 1 interrupt
- OR AL,ier_8250_thre+ier_8250_ms ; Yes - We need both modem status enable
- ; and THRE interrupts too
- rsint_8250_initnotr:
-
- MOV DX,CX ; Compute port address for the IER
- ADD DX,ier_8250 ;
- OUT DX,AL ; Set the IER
-
- ;--------------------------------------------------------------------------;
- ; Done with initialization ;
- ;--------------------------------------------------------------------------;
-
- JMP rsint_8250_status ; Now just status please
-
- ;==========================================================================;
- ; Send a character ;
- ;==========================================================================;
-
- ;--------------------------------------------------------------------------;
- ; There are two places where the branch from the non-interrupt ;
- ; driven code to the interrupt driven code is taken so be careful ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_send:
-
- MOV AH,AL ; Save the character to send
- MOV CX,baseaddr[SI] ; Get base address for chip
-
- ;--------------------------------------------------------------------------;
- ; Two separate routines, one for trasmit buffering and one if not! ;
- ;--------------------------------------------------------------------------;
-
- TEST options[SI],opt_trbuf ; Transmit buffering turned on?
- JNZ rsint_8250_send_bh ; Yes.. go there now!
-
- ;--------------------------------------------------------------------------;
- ; Unbuffered send ;
- ;--------------------------------------------------------------------------;
-
- CALL rsint_8250_send_unb ; Send unbuffered
- JMP rsint_8250_status ; Go do a status
-
- ;--------------------------------------------------------------------------;
- ; Buffered send starts here ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_send_bh:
-
- CLI ; Prevent status change
-
- TEST options[SI],opt_hdwhs ; Hardware handshaking desired?
- JZ rsint_8250_sendb_ok ; Nope
-
- ;--------------------------------------------------------------------------;
- ; Buffered send -- hardware handshaking. If the remote says no, go ;
- ; immediately to buffered send ;
- ;--------------------------------------------------------------------------;
-
- CALL rsint_8250_msr ; Get the MSR
- AND AL,msr_8250_cts ; CTS on?
- JZ rsint_8250_sendb_fb ; Go to a spot where buffering is forced
-
- ;--------------------------------------------------------------------------;
- ; This section is entered when its ok to send a character if the ;
- ; buffer is empty. Its either entered by the buffer handler above ;
- ; when handshaking is enabled and the remote says go or from the ;
- ; non-interrupt driven code if there is no handshaking ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_sendb_ok:
-
- ;--------------------------------------------------------------------------;
- ; Here we determine if the buffer is empty. If it is, we can send ;
- ; something right now. ;
- ;--------------------------------------------------------------------------;
-
- MOV BX,buffer_t_in[SI] ; Get buffer input pointer
- CMP BX,buffer_t_out[SI] ; See where the out pointer is
- JNE rsint_8250_sendb_fb2; If they are not equal then we have
- ; data in the buffer
-
- MOV DX,CX ; Compute port address for the LSR
- ADD DX,lsr_8250 ;
- IN AL,DX ; Get the LSR into AX
- AND AL,lsr_8250_thre ; THR empty?
- JZ rsint_8250_sendb_fb2; No.. Put character into the buffer
-
- STI ; AOK now
-
- ; If we get here, the buffer is empty, the transmitter is ready, and
- ; handshaking says it is ok to go!
-
- CALL rsint_8250_send_subr ; Send the character
-
- JMP SHORT rsint_8250_send_exit ; Now jump down to leave
-
- ;--------------------------------------------------------------------------;
- ; This code puts the data into the buffer. ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_sendb_fb: ; Use this entry point if hardware
- ; handshake says distant end is not ready
- ; We have to do some setup
-
- MOV BX,buffer_t_in[SI] ; Get buffer input pointer
-
- rsint_8250_sendb_fb2: ; Use this entry point if hardware
- ; handshake was ok or not enabled.
- ; All the setup is done when we get here
-
- MOV ES,buffer_t_a[SI] ; Get buffer segment
- MOV ES:[BX],AH ; Get character into buffer..
-
- ;--------------------------------------------------------------------------;
- ; Bump the input pointer and handle the special case of where we wrap ;
- ; from one end of the buffer into the other ;
- ;--------------------------------------------------------------------------;
-
- INC BX ; Bump pointer
- CMP BX,buffer_size ; Have we wrapped the buffer?
- JL rsint_8250_sendb_bump ; No.. All done
- SUB BX,BX ; Yes.. Reset pointer
- rsint_8250_sendb_bump:
-
- MOV buffer_t_in[SI],BX ; Save pointer
-
- STI ; OK for changes now...
-
- ;--------------------------------------------------------------------------;
- ; If we have a destructive overlay possible then loop waiting for it to ;
- ; clear. Since the pointer in BX is to the location of the next character ;
- ; the we will overlap if it is the same as the pointer for the next ;
- ; character to send. The actual sending will be done by the interrupt ;
- ; handler. All we have to do is waint until the interrupt handler ;
- ; has cleaned some characters out of the buffer ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_sendb_bad:
- CMP BX,buffer_t_out[SI] ; See where the out pointer is
-
- IF present_dv ; Put in the desqview wait hook as needed
-
- JNE rsint_8250_send_exit ; If they are not equal then we are ok
- dv_cnt = dv_cnt + 1
- dv_hook %dv_cnt
- CALL desqview
- JMP SHORT rsint_8250_sendb_bad
-
- ELSE
-
- JE rsint_8250_sendb_bad ; If they are not equal then we are ok
-
- ENDIF
-
- ;--------------------------------------------------------------------------;
- ; We come here when we have sent the character immediately. ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_send_exit:
-
- ;--------------------------------------------------------------------------;
- ; All done, do a status ;
- ;--------------------------------------------------------------------------;
-
- JMP rsint_8250_status ; Do a status
-
- ;--------------------------------------------------------------------------;
- ;--------------------------------------------------------------------------;
- ; Subroutine to send unbuffered ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_send_unb:
-
- TEST options[SI],opt_hdwhs ; Hardware handshaking desired?
- JZ rsint_8250_send_nbok ; Nope
-
- IF present_dv ;
- JMP SHORT rsint_8250_send_nbl_dv ; First time jump over dv hook
- ENDIF
-
- ; Hardware handshake loop for unbuffered sending
-
- rsint_8250_send_nbl: ; Loop here until we can send
-
- IF present_dv ; Put in the desqview wait hook as needed
-
- dv_cnt = dv_cnt + 1
- dv_hook %dv_cnt
- CALL desqview
-
- rsint_8250_send_nbl_dv: ; Enter loop here when in desqview
-
- ENDIF
-
-
- CALL rsint_8250_msr ; Get the MSR
-
- AND AL,msr_8250_cts ; CTS on?
- JZ rsint_8250_send_nbl ; No.. Loop back
-
- rsint_8250_send_nbok: ;
-
- ; Unbuffered sending.. Now ready to transmit
- ; ***** FALL THRU
-
- ;--------------------------------------------------------------------------;
- ;--------------------------------------------------------------------------;
- ; Subroutine to send the character in AH ;
- ; *** WARNING *** also entered by fall thru from above ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_send_subr:
-
- ;--------------------------------------------------------------------------;
- ; Loop waiting for TBE ;
- ;--------------------------------------------------------------------------;
-
- MOV DX,CX ; Compute port address for the LSR
- ADD DX,lsr_8250 ;
-
- IF present_dv ; Put in the desqview wait hook as needed
- JMP SHORT rsint_8250_send_sublp_dv ; First time jump over dv hook
- ENDIF
-
- rsint_8250_send_sublp: ; Loop here until we can send
-
- IF present_dv ; Put in the desqview wait hook as needed
-
- dv_cnt = dv_cnt + 1
- dv_hook %dv_cnt
- CALL desqview
-
- rsint_8250_send_sublp_dv: ; First time we jump here in desqview mode
-
- ENDIF
-
- IN AL,DX ; Get the LSR into AX
- AND AL,lsr_8250_thre ; THR empty?
- JZ rsint_8250_send_sublp ; No.. Loop back
-
- ;--------------------------------------------------------------------------;
- ; Out the character ;
- ;--------------------------------------------------------------------------;
-
- MOV AL,AH ; Get ready to out character
-
- MOV DX,CX ; Compute port address for the THR
- ; ADD DX,thr_8250 ; and then
- OUT DX,AL ; out the character
- ; The add of THR is commented out since the THR is at zero from
- ; the base. This just documents the fact we are going for the THR
-
- ;--------------------------------------------------------------------------;
- ; Turn on the character sent flag ;
- ;--------------------------------------------------------------------------;
-
- OR flags[SI],flags_xmt_on ; Turn on transmitter flag
-
- RET ; Return to sender
-
- ;==========================================================================;
- ; Receive a character ;
- ;==========================================================================;
-
- rsint_8250_recv:
-
- MOV CX,baseaddr[SI] ; Get base address for chip
-
- ;--------------------------------------------------------------------------;
- ; Loop waiting for something to appear in the buffer. We do this ;
- ; by comparing the input and output pointers. If they are the same ;
- ; same then there is nothing in the buffer ;
- ;--------------------------------------------------------------------------;
-
- MOV BX,buffer_r_out[SI] ; Get buffer output pointer
-
- IF present_dv ; If desqview presentthen skip the hook
- JMP SHORT rsint_8250_recv_rdy
- ENDIF
-
- rsint_8250_recv_loop:
-
- IF present_dv ; Put in the desqview wait hook as needed
-
- dv_cnt = dv_cnt + 1
- dv_hook %dv_cnt
- CALL desqview
-
- rsint_8250_recv_rdy: ; Come here to start when in desqview mode
-
- ENDIF
-
-
- CMP BX,buffer_r_in[SI] ; See in anything in buffer
- JE rsint_8250_recv_loop ; Nope.. Keep looping
-
- ;--------------------------------------------------------------------------;
- ; Something is here.. Remove the character from the buffer ;
- ;--------------------------------------------------------------------------;
-
- MOV ES,buffer_r_a[SI] ; Get buffer segment
- MOV AH,ES:[BX] ; Get character from buffer.. Hide it in AH
-
- ;--------------------------------------------------------------------------;
- ; Bump the output pointer and handle the special case of where we wrap ;
- ; from one end of the buffer into the other ;
- ;--------------------------------------------------------------------------;
-
- INC BX ; Bump pointer
- CMP BX,buffer_size ; Have we wrapped the buffer?
- JL rsint_8250_recv_exit ; No.. All done
- SUB BX,BX ; Yes.. Reset pointer
- rsint_8250_recv_exit:
-
- MOV buffer_r_out[SI],BX ; Save pointer
-
- ;--------------------------------------------------------------------------;
- ; If we have hardware handshaking enabled, then see if we need to ;
- ; signal start. 1/16 is the limit we are using ;
- ;--------------------------------------------------------------------------;
-
- TEST options[SI],opt_hdwhs ; Hardware handshaking desired?
- JZ rsint_8250_r_nohshak ; Nope
- TEST flags[SI],flags_useoff ; Does user wants handshake off?
- JNZ rsint_8250_r_nohshak ; Yep... We dont touch it here
-
- MOV DX,BX ; Put pointer in work reg
- SUB DX,buffer_r_in[SI] ; Compute the delta
- JG rsint_8250_rpos ; Jump over if positive result
- ADD DX,buffer_size ; This will convert it back to positive
- rsint_8250_rpos: ; DX now is equal to bytes free!
-
- CMP DX,(buffer_size / 8) ; See if at least 1/8 is left
- JL rsint_8250_r_stop ; No... Leave stop on
-
- MOV DX,CX ; Get base address for chip
- ADD DX,mcr_8250 ;
- MOV AL,hon_8250 ; Raise DTR, RTS, and OUT2. OUT2 turns
- OUT DX,AL ; on interrupts.
-
- rsint_8250_r_stop: ;
-
- rsint_8250_r_nohshak: ;
-
- ;--------------------------------------------------------------------------;
- ; Remember we hid the receive character in AH... Put it where it belongs ;
- ; now ;
- ;--------------------------------------------------------------------------;
-
- MOV AL,AH ;
-
- ;--------------------------------------------------------------------------;
- ; Put out the last LSR we received with the exception of RDA. If we have ;
- ; no pending LSR, go get one ;
- ;--------------------------------------------------------------------------;
-
- SUB AH,AH ; Get the last LSR and
- XCHG AH,last_rs[SI] ; clear it too!
-
- OR AH,AH ; Is it non-existant?
- JNZ rsint_8250_rcv_nolsr; Nope
-
- MOV AH,AL ; Save the received character
-
- MOV DX,CX ; Get base address for chip
- ADD DX,lsr_8250 ; Now get a real LSR
- IN AL,DX ;
-
- XCHG AH,AL ; Put things back together
-
- rsint_8250_rcv_nolsr:
-
- ;--------------------------------------------------------------------------;
- ; Set the RDA bit based on buffer status ;
- ;--------------------------------------------------------------------------;
-
- AND AH,0FFH-lsr_8250_dr ; Remove data ready bit
-
- CMP BX,buffer_r_in[SI] ; Anything left in buffer?
- JE rsint_8250_rcv_go ; Nope so leave
- OR AH,lsr_8250_dr ; Turn on data ready
- rsint_8250_rcv_go: ;
-
- ;--------------------------------------------------------------------------;
- ; Done ;
- ;--------------------------------------------------------------------------;
-
- JMP rsint_exit ; and go leave
-
- ;==========================================================================;
- ; Status.. Return the MSR and the LSR ;
- ;==========================================================================;
-
- rsint_8250_status:
-
- MOV CX,baseaddr[SI] ; Get base address for chip
-
- ;--------------------------------------------------------------------------;
- ; Put out the current LSR plus the current Receive Data Available ;
- ; setting based on the buffer contents plus last_lsr ;
- ;--------------------------------------------------------------------------;
-
- MOV DX,CX ; Compute port address for the LSR
- ADD DX,lsr_8250 ; and then
- JMP $+2 ;
- IN AL,DX ; get it
-
- SUB AH,AH ; Get the last LSR and clear it too.
- XCHG AH,last_rs[SI] ;
- OR AL,AH ; OR it in
-
- AND AL,0FFH-lsr_8250_dr ; Remove data ready bit
-
- MOV BX,buffer_r_out[SI] ; Get buffer output pointer
- CMP BX,buffer_r_in[SI] ; Anything left in buffer?
- JE rsint_8250_status_nodr ; Nope so leave
- OR AL,lsr_8250_dr ; Turn on data ready
- rsint_8250_status_nodr:
-
- MOV AH,AL ; Save LSR
-
- ;--------------------------------------------------------------------------;
- ; Now lets get the MSR ;
- ;--------------------------------------------------------------------------;
-
- CALL rsint_8250_msr ; Get the MSR
-
- ;--------------------------------------------------------------------------;
- ; Save both the real LSR and the real MSR for later ;
- ;--------------------------------------------------------------------------;
-
- MOV DX,AX ;
-
- ;--------------------------------------------------------------------------;
- ; If we have transmit buffering active then we adjust the TBE and CTS ;
- ; bits based on current state of transmit buffers etc... ;
- ;--------------------------------------------------------------------------;
-
- TEST options[SI],opt_trbuf ; Transmit buffering turned on?
- JZ rsint_8250_status_notb; Nope... Skip this
-
- ;--------------------------------------------------------------------------;
- ; If the buffer is empty, use the TBE as set by the chip. In all ;
- ; other cases, TBE should be off since there is data in the buffer ;
- ;--------------------------------------------------------------------------;
-
- MOV BX,buffer_t_out[SI] ; Get buffer output pointer
- SUB BX,buffer_t_in[SI] ; Get buffer input pointer
- JG rsint_8250_status_tpos ; Jump over if positive result
- ADD BX,buffer_size ; This will convert it back to positive
- rsint_8250_status_tpos: ; BX now is equal to bytes left!
-
- CMP BX,buffer_size ; Max amount left in buffer?
- JE rsint_8250_status_empty; Yes.. Use the chip's THRE
-
- AND AH,0FFH-lsr_8250_thre ; Remove transmit holding register empty
- rsint_8250_status_empty:
-
- ;--------------------------------------------------------------------------;
- ; Hardware handshaking? If not, we can go ;
- ;--------------------------------------------------------------------------;
-
- TEST options[SI],opt_hdwhs ; Hardware handshaking desired?
- JZ rsint_8250_t_nostop ; Nope... we are done
-
- ;--------------------------------------------------------------------------;
- ; If the remote signals stop, so will we... ;
- ;--------------------------------------------------------------------------;
-
- TEST DL,msr_8250_cts ; See Clear to send (CTS) on from remote?
- JZ rsint_8250_status_tstop ; Nope..... Stop sending!
-
- ;--------------------------------------------------------------------------;
- ; Now we assume that we have a CTS on! .. ;
- ;--------------------------------------------------------------------------;
-
- OR AL,msr_8250_cts ; Set Clear to send (CTS)
-
- ; CTS is already on...
- ; becuz there is data in the buffer
-
- ;--------------------------------------------------------------------------;
- ; See if any room left in buffer. If so, we can go ;
- ;--------------------------------------------------------------------------;
-
- CMP BX,(buffer_size / 4) ; See if at least 1/4 is left
- JGE rsint_8250_t_nostop ; Yes.. No stop needed
-
- ;--------------------------------------------------------------------------;
- ; Signal to stop sending! ;
- ;--------------------------------------------------------------------------;
-
- rsint_8250_status_tstop:
-
- AND AH,0FFH-lsr_8250_thre ; Remove transmit holding register empty
- AND AL,0FFH-msr_8250_cts ; Remove Clear to send (CTS)
-
- rsint_8250_t_nostop:
-
- rsint_8250_status_notb:
-
- ;--------------------------------------------------------------------------;
- ; All done ;
- ;--------------------------------------------------------------------------;
-
- JMP rsint_exit ; All done
-
- ;==========================================================================;
- ; Subroutine to get the MSR... Why is special??? Because it could ;
- ; accidentally wipe out the pending modem state change interrupt ;
- ; Inputs : CX = port base address ;
- ; Outputs : AL = MSR ;
- ; Registers used: DX ;
- ;==========================================================================;
-
- rsint_8250_msr:
-
- MOV DX,CX ; Compute port address for the MSR
- ADD DX,msr_8250 ; and then
- IN AL,DX ; get it
- TEST AL,msr_8250_dcts ; Delta CTS?
- JZ SHORT rsint_8250_msr_exit ; Nope..... leave...
- TEST AL,msr_8250_cts ; CTS on?
- JZ SHORT rsint_8250_msr_exit ; Nope..... leave...
-
- ; We have accidentally eaten an interrupt intended for the handler...
- ; Now create a pseudo interrupt!
-
- MOV DL,hiv[SI] ; Get the hardware interrupt vector address
- MOV rsint_8250_msr_int,DL ; Put it where we need it
-
- JMP $+2 ; Clean out prefetch stack
- INT 00H ; Interrupt!
- ORG $-1
- rsint_8250_msr_int DB ? ; Place to put interrupt number
-
- ; We are going to exit here with interrupt
- ; masked since we will exit in a very very short
- ; time
-
- rsint_8250_msr_exit:
- RET ; Return to caller
-
- ;==========================================================================;
- ; Extended service routines are below (if any) ;
- ;==========================================================================;
-
- IF present_8250x
-
- INCLUDE 8250svcx.asm ;
-
- ENDIF